#include "ralist.h"
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int ralCompare(list *l, srvAddress *addr)
{
    return memcmp(&l->addr, addr, sizeof(srvAddress));
}


ralIterator *ralCreateIterator(ralist *ral)
{
    ralIterator *it;

    it = malloc(sizeof(ralIterator));
    if(!it) return NULL;

    it->next = ral->head;
    it->len  = ral->len;
    it->index= 0;

    return it;
}

ralIterator *ralRewindIterator(ralist *ral, ralIterator *it)
{
    it->next = ral->head;
    it->len  = ral->len;
    it->index= 0;
    return it;
}

list *ralIteratorNext(ralIterator *it)
{
    list *l = NULL;

    if(it->len > 0 && it->index < it->len){
        l = it->next;
        it->next = l->next;
        it->index ++;
    }

    return l;
}

list *ralIteratorLoopNext(ralIterator *it)
{
    list *l = NULL;

    if(it->len){
        l = it->next;
        it->next = l->next;
    }

    return l;
}

void ralIteratorRelease(ralIterator *it)
{
    if(it)free(it);
}

void ralPrint(ralist *ral)
{
    ralIterator *it;
    list *l;

    printf("len:%d\n", ral->len);
    it = ralCreateIterator(ral);
    while((l = ralIteratorNext(it))){
        printf("ip:%d, port:%d, last:%lu\n", l->addr.ip, l->addr.port, l->last);
    }
    ralIteratorRelease(it);
}

char *ralAcquireAllAddress(ralist *ral)
{
    ralIterator *it;
    list *l;
    char *buf;
    int i = 0;
    int ret;
    int len;

    len = ral->len * 30;
    if(len == 0) return NULL;
    buf = malloc(len);
    if(!buf) return NULL;

    it = ralCreateIterator(ral);
    while((l = ralIteratorNext(it))){
        ret = snprintf(buf + i, len - i, "%s:%d\r\n", 
                inet_ntoa(*(struct in_addr*)&l->addr.ip), ntohs(l->addr.port));
        i += ret;
    }
    ralIteratorRelease(it);
    return buf;
}

void ralReleaseAcquireAddress(char *buf)
{
    if(buf) free(buf);
}


ralist *ralCreate(void)
{
    ralist * ral;

    ral = malloc(sizeof(ralist));
    if(!ral)return NULL;

    ral->head = NULL;
    ral->len  = 0;
    return ral;
}

void ralDelete(ralist *ral, list *l)
{
    if(ral->len){
        ral->len--;
        if(0 == ral->len) ral->head = NULL;
        else if(l == ral->head) ral->head = l->next;
        l->prev->next = l->next;
        l->next->prev = l->prev;
        if(l->fd > 0) close(l->fd), l->fd = -1;
        free(l);
    }
}

int ralRelease(ralist *ral)
{
    ralIterator *it;
    list *l;

    it = ralCreateIterator(ral);
    if(!it) return -1;
    while((l = ralIteratorNext(it))){
        ralDelete(ral, l);
    }
    ralIteratorRelease(it);
    free(ral);

    return 0;
}

list* ralFind(ralist *ral, srvAddress *addr)
{
    ralIterator *it;
    list *l = NULL;

    it = ralCreateIterator(ral);
    if(!it) return NULL;
    
    while((l = ralIteratorNext(it))){
        if(0 == ralCompare(l, addr)){
            break;
        }
    }

    ralIteratorRelease(it);
    return l;
}

list* ralAddHead(ralist *ral, int fd, void *comm, srvAddress *addr)
{
    list *l;

    l = malloc(sizeof(list));
    if(!l) return NULL;
    
    l->fd = fd;
    l->comm = comm;
    l->last = time(NULL);
    memcpy(&l->addr, addr, sizeof(srvAddress));
    if(!ral->head){
        l->next = l;
        l->prev = l;
    }
    else{
        l->next = ral->head;
        ral->head->prev->next = l;
        l->prev = ral->head->prev;
        ral->head->prev = l;
    }
    ral->head = l;
    ral->len++;
    return l;    
}

